package web

import (
	"fmt"
	"gitee.com/then-go-project/go-utils/base"
	"github.com/gin-contrib/pprof"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"net/http"
	"time"
)

type RecordLog interface {
	RecordLog(url string, req, res interface{}, success bool, Headers http.Header)
}

var rl RecordLog

func errorRecover(c *gin.Context) {
	defer func() {
		if r := recover(); r != nil {
			switch r.(type) {
			case error:
				base.ZapLog.Error(fmt.Sprintf("%s", InternalErrMsg), zap.Error(r.(error)), zap.Stack("error stack"))
			default:
				base.ZapLog.Error(fmt.Sprintf("%s，%v", InternalErrMsg, r), zap.Stack("error stack"))
			}
			RespFail(c, InternalErr, InternalErrMsg)
			c.Abort()
		}
	}()
	c.Next()
}

func ginLogger(c *gin.Context) {
	start := time.Now()
	path := c.Request.URL.Path
	query := c.Request.URL.RawQuery
	c.Next()

	cost := time.Since(start)
	base.ZapLog.Debug(path,
		zap.Int("status", c.Writer.Status()),
		zap.String("method", c.Request.Method),
		zap.String("path", path),
		zap.String("query", query),
		zap.String("ip", c.ClientIP()),
		zap.String("user-agent", c.Request.UserAgent()),
		zap.String("errors", c.Errors.ByType(gin.ErrorTypePrivate).String()),
		zap.Duration("cost", cost),
	)
}

func GenerateService(isDebug bool, rls ...RecordLog) *gin.Engine {
	var router *gin.Engine

	if isDebug {
		gin.SetMode(gin.DebugMode)
		router = gin.New()
		pprof.Register(router)
	} else {
		gin.SetMode(gin.ReleaseMode)
		router = gin.New()
	}

	router.Use(ginLogger, errorRecover)

	if len(rls) > 0 {
		rl = rls[0]
	}
	return router
}
